﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Zhaoxi.AdvancedCourse.Models;

namespace Zhaoxi.AdvancedCourse.GenericClasses
{
    /// <summary>
    /// 泛型方法类
    /// </summary>
    public class GenericMethodClass
    {
        /// <summary>
        /// 普通泛型方法
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="tParameter"></param>
        public static void ShowGeneric<T>(T tParameter)
        {
            Console.WriteLine($"This is {typeof(GenericMethodClass).Name},parameter={tParameter.GetType().Name},type={tParameter}");
        }

        //T 类型占位符  不确定的类型 
        //泛型方法   方法名<T>
        public static string GetClassType<T>(T obj)
        {
            return obj.GetType().Name;
        }

        /// <summary>
        /// 获取泛型类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static string GetClassType<T>()
        {
            return typeof(T).Name;
        }

        /// <summary>
        /// 值类型约束与引用类型约束不能同时使用
        /// 值类型约束  where T:struct
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="str"></param>
        /// <returns></returns>
        public static T ToType<T>(string str) where T : struct
        {
            Type type = typeof(T);
            return (T)Convert.ChangeType(str, type);
        }

        /// <summary>
        /// 引用类型约束 where T : class
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dr"></param>
        /// <returns></returns>
        public static T ClassToModel<T>(DataRow dr) where T : class
        {
            Type type = typeof(T);
            return (T)Convert.ChangeType(dr, type);
        }

        /// <summary>
        /// 基类约束不能与引用类型约束同时设置
        /// 基类约束  where T:RecordBase  调用时的实际类型必须是RecordBase类型或其子类
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        public static void GetRecordInfo<T>(T t) where T : RecordBase
        {
            Console.WriteLine("编号：" + t.Id + ", 描述：" + t.Remark + ", 金额：" + t.Amount); // 因为是基类约束所以可以直接使用属性
        }

        public static decimal totalAmount = 0.00m;//总收支

        /// <summary>
        /// 基类约束+接口约束-----基类约束写在前面
        /// 计算总收支
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <returns></returns>
        public static decimal GetTotalAmount<T>(T t) where T : RecordBase, IRecord
        {
            return t.CalTotalAmount(t.Amount); // 实现接口
        }

        /// <summary>
        /// 基类约束+接口约束+无参构造函数约束
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static  T Create<T>() where T:RecordBase,IRecord,new()
        {
            T t = new T();
            return t;
        }

        /// <summary>
        /// 无参构造函数约束
        /// 可以和引用类型、基类型约束共存
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static T CreateModel<T>() where T : new()
        {
            T t = new T(); // 无参构造函数主要用于在泛型未确定类型前进行实例化的。
            return t;
        }

        /// <summary>
        /// 引用类型约束+无参构造函数约束
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dr"></param>
        /// <returns></returns>
        public static T RowToModel<T>(DataRow dr) where T:class,new()
        {  // 这里将DataRow转换成一个对象-这个时候使用无参构造函数约束就可以创建一个T对象然后返回。
            T t = new T();  // 只有无参构造函数才可以自己new
            //中间需要涉及反射的使用？？？？？？

            return t;
        }

        /// <summary>
        /// 通过反射动态实例化泛型对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static T CreateObj<T>() where T:class
        {
            // T t = new T();
            T t = null;
         //   t=(T)Activator.CreateInstance(typeof(T));
         t=Activator.CreateInstance<T>();
            return t;
        }

        /// <summary>
        /// 计算器泛型方法
        /// where T : struct, T1, T2 设置返回类型T、T1、T2都是数值类型
        /// </summary>
        /// <typeparam name="T">返回类型</typeparam>
        /// <typeparam name="T1">第一个操作数类型</typeparam>
        /// <typeparam name="T2">第二个操作数类型</typeparam>
        /// <param name="num1">参数1</param>
        /// <param name="num2">参数2</param>
        /// <returns>操作结果</returns>
        public T Add<T, T1, T2>(T1 num1, T2 num2) where T : struct, T1, T2  
        {
            // dynamic是动态类型-运行的时候解析的类型
            dynamic a = num1;
            dynamic b = num2;
            return a + b;
        }

    }
}
